const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("HeroCard", function () {
  async function deployHeroCardFixture() {
    const [owner, addr1, addr2] = await ethers.getSigners();
    const HeroCard = await ethers.getContractFactory("HeroCard");
    const heroCard = await HeroCard.deploy();
    return { heroCard, owner, addr1, addr2 };
  }

  describe("Deployment", function () {
    it("Should set the right owner", async function () {
      const { heroCard, owner } = await loadFixture(deployHeroCardFixture);
      expect(await heroCard.owner()).to.equal(owner.address);
    });
  });

  describe("Hero Management", function () {
    it("Should create a new hero with correct attributes", async function () {
      const { heroCard, owner } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Test Hero", 100, 50, 10);
      const hero = await heroCard.getHeroAttributes(1);
      expect(hero.name).to.equal("Test Hero");
      expect(hero.power).to.equal(100);
      expect(hero.cost).to.equal(50);
      expect(hero.isActive).to.equal(true);
    });

    it("Should mint correct amount of hero cards", async function () {
      const { heroCard, owner } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Test Hero", 100, 50, 10);
      expect(await heroCard.balanceOf(owner.address, 1)).to.equal(10);
    });

    it("Should allow batch minting of existing heroes", async function () {
      const { heroCard, owner, addr1 } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Hero 1", 100, 50, 1);
      await heroCard.createHero("Hero 2", 200, 100, 1);
      
      const ids = [1, 2];
      const amounts = [5, 3];
      await heroCard.mintBatch(addr1.address, ids, amounts);
      
      expect(await heroCard.balanceOf(addr1.address, 1)).to.equal(5);
      expect(await heroCard.balanceOf(addr1.address, 2)).to.equal(3);
    });
  });

  describe("Hero Status Management", function () {
    it("Should allow owner to change hero status", async function () {
      const { heroCard } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Test Hero", 100, 50, 10);
      await heroCard.setHeroStatus(1, false);
      const hero = await heroCard.getHeroAttributes(1);
      expect(hero.isActive).to.equal(false);
    });
  });

  describe("URI Management", function () {
    it("Should set and get correct URI", async function () {
      const { heroCard } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Test Hero", 100, 50, 10);
      await heroCard.setBaseURI("https://example.com/");
      expect(await heroCard.uri(1)).to.equal("https://example.com/1");
    });
  });

  describe("User Cards Query", function () {
    it("Should return correct user cards information", async function () {
      const { heroCard, owner } = await loadFixture(deployHeroCardFixture);
      await heroCard.createHero("Hero 1", 100, 50, 5);
      await heroCard.createHero("Hero 2", 200, 100, 3);
      
      const [cardIds, balances, attributes] = await heroCard.getUserCards(owner.address);
      
      expect(cardIds.length).to.equal(2);
      expect(balances[0]).to.equal(5);
      expect(balances[1]).to.equal(3);
      expect(attributes[0].name).to.equal("Hero 1");
      expect(attributes[1].name).to.equal("Hero 2");
    });
  });
});